﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Q.Framework.ValueObject
{
    public enum FormatTime { HourMinute, HourMinuteSecond };
    public class Time
    {
        public Int32 Hour { get; set; }
        public Int32 Minute { get; set; }
        public Int32 Second { get; set; }
        public Int32 TotalSeconds
        {
            get { return (((Hour * 60) + Minute) * 60) + Second; }
        }

        public Time() { }
        public Time(Int32 hour, Int32 minute, Int32 second)
        {
            Hour = hour;
            Minute = minute;
            Second = second;
        }

        public static Time Parse(String value)
        {
            if (String.IsNullOrWhiteSpace(value) || value.Length < 4 || value.Length > 8 || !new[] { 4, 5, 8 }.Contains(value.Length) || value.IndexOf(':') < 0)
                throw new FormatException("Input string was not in a correct format");
            String[] sArr = value.Split(':');
            if (sArr.Length > 3 && sArr.Length < 2)
                throw new FormatException("Input string was not in a correct format");
            if (sArr.Any(s => s.Length > 2))
                throw new FormatException("Input string was not in a correct format");

            Int32[] iArr = new Int32[3];

            for (int i = 0; i < sArr.Length; i++)
            {
                if (i == 0)
                    sArr[i] = sArr[i].PadLeft(2, '0');
                else if(sArr[i].Length < 2)
                    throw new FormatException("Input string was not in a correct format");
                Int32 t = 0;
                if(!Int32.TryParse(sArr[i], out t))
                    throw new FormatException("Input string was not in a correct format");
                if (i == 0)
                {
                    if(t > 23 || t < 0)
                        throw new FormatException("Input string was not in a correct format");
                }
                else if(t > 59 || t < 0)
                    throw new FormatException("Input string was not in a correct format");
                iArr[i] = t;
            }

            return new Time(iArr[0], iArr[1], iArr[2]);
        }

        public static Boolean TryParse(String s, out Time result)
        {
            try
            {
                result = Parse(s);
                return true;
            }
            catch (FormatException)
            {
                result = new Time();
                return false;
            }
        }

        public static Boolean operator >(Time h1, Time h2)
        {
            return h1.TotalSeconds > h2.TotalSeconds;
        }

        public static Boolean operator <(Time h1, Time h2)
        {
            return h1.TotalSeconds < h2.TotalSeconds;
        }

        public static Boolean operator ==(Time h1, Time h2)
        {
            return h1.TotalSeconds == h2.TotalSeconds;
        }

        public static Boolean operator !=(Time h1, Time h2)
        {
            return h1.TotalSeconds != h2.TotalSeconds;
        }

        public static implicit operator Time(DateTime s)
        {
            return new Time(s.Hour, s.Minute, s.Second);
        }

        public static Boolean operator >(Time h1, TimeSpan h2)
        {
            return h1.TotalSeconds > h2.TotalSeconds;
        }

        public static Boolean operator <(Time h1, TimeSpan h2)
        {
            return h1.TotalSeconds < h2.TotalSeconds;
        }

        public static Boolean operator ==(Time h1, TimeSpan h2)
        {
            return h1.TotalSeconds == h2.TotalSeconds;
        }

        public static Boolean operator !=(Time h1, TimeSpan h2)
        {
            return h1.TotalSeconds != h2.TotalSeconds;
        }

        public String Format(FormatTime format = FormatTime.HourMinute)
        {
            List<Int32> iList = new List<int>();
            iList.Add(Hour);
            iList.Add(Minute);
            if (format == FormatTime.HourMinuteSecond)
                iList.Add(Second);
            return String.Join(":", iList);
        }

        public override string ToString()
        {
            return Format(FormatTime.HourMinuteSecond);
        }
    }
}
